package net.jumpengine.manager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import net.jumpengine.Manager;
import net.jumpengine.bean.Base;
import net.jumpengine.event.KeyMiddle;
import net.jumpengine.event.MouseMiddle;
import net.jumpengine.inter.IClick;
import net.jumpengine.inter.IControl;
import net.jumpengine.inter.IInputEvent;
import net.jumpengine.inter.IMouseEvent;
import net.jumpengine.inter.IStateEvent;
import net.jumpengine.util.UCollision;
import net.jumpengine.util.UComm;

/**
 * 游戏引擎的事件管理类
 * <br /><br />
 * <b>作者:&nbsp;</b>张天文 <br />
 * <b>日期:&nbsp;</b>2020年2月26日 下午4:18:52<br />
 * @date
 */
public class EventManager  {
	private MouseMiddle mouse=new MouseMiddle();
	private KeyMiddle input=new KeyMiddle();
	private Map<Enum<?>,IStateEvent> stateMap=new HashMap<>();
	private Map<Enum<?>,List<Base>> clickMap=new HashMap<>();
	private boolean clickChanged=false;
	
	/**
	 * 初始化事件管理器, 对窗体添加监听
	 * @param group
	 * @param scene
	 */
	public void init(Group group,Scene scene) {
		Manager.getLog().debug("EventManager[init]");
		
		group.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				mouse.click((int)event.getSceneX(),(int)event.getSceneY(),event.getButton());		
			}
		});
		group.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				mouse.move((int)event.getSceneX(),(int)event.getSceneY(),event.getButton());			
			}
		});
		group.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				mouse.pressed((int)event.getSceneX(),(int)event.getSceneY(),event.getButton());				
			}
		});
		group.addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				mouse.released((int)event.getSceneX(),(int)event.getSceneY(),event.getButton());					
			}
		});
		
		scene.addEventHandler(KeyEvent.KEY_PRESSED,new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent event) {
				input.pressed(event.getCharacter(),event.getCode(),event.getText());
			}
		});
		scene.addEventHandler(KeyEvent.KEY_RELEASED,new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent event) {
				input.released(event.getCharacter(),event.getCode(),event.getText());
			}
		});
		scene.addEventHandler(KeyEvent.KEY_TYPED,new EventHandler<KeyEvent>() {
			@Override
			public void handle(KeyEvent event) {
				input.typed(event.getCharacter(),event.getCode(),event.getText());
			}
		});
	}
	
	/**
	 * 添加鼠标事件处理类
	 * @param t 游戏状态
	 * @param obj 鼠标事件处理类
	 */
	public void addMouseEvent(Enum<?> e,IMouseEvent obj) {
		mouse.put(e, obj);
	}
	
	/**
	 * 添加按键事件管理类
	 * @param t 游戏状态
	 * @param obj 按键事件管理类
	 */
	public void addInputEvent(Enum<?> e,IInputEvent obj) {
		input.put(e,obj);
	}
	
	/**
	 * 添加游戏状态管理类
	 * @param t 游戏状态
	 * @param obj 游戏状态管理类
	 */
	public void addStateEvent(Enum<?> e,IStateEvent obj) {
		stateMap.put(e, obj);
	}
	
	public IStateEvent getStateEvent(Enum<?> e) {
		return stateMap.get(e);
	}
	
	/**
	 * 添加控件,用于imageManager.add的后续调用
	 * @param t 游戏状态
	 * @param base 继承了IClick接口的Base会添加到控件集合
	 */
	public void addClick(Enum<?> t,Base base) {
		if(base instanceof IClick) {
			List<Base> list = clickMap.get(t);
			if(list==null) {
				list=new ArrayList<Base>();
				clickMap.put(t, list);
			}
			list.add(base);
			clickChanged=true;
		}
	}
	
	/**
	 * 根据坐标找到有点击事件的Base, 根据Base排序后, 反序查找, 可以先找到index最大, 尺寸最小的Base
	 * @param x x坐标
	 * @param y y坐标
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T extends Base> T FindBaseByPoint(int x,int y,Class<T> c) {
		List<Base> list = clickMap.get(Manager.getState());
		if(UComm.isNull(list))return null;
		if(clickChanged) {
			Collections.sort(list);
			clickChanged=false;
		}
		Base base;
		IControl ic;
		for(int i=list.size()-1;i>=0;i--) {
			base=list.get(i);
			if(c.isAssignableFrom(base.getClass())) {
				if(base instanceof IControl) {
					ic=(IControl) base;
					if(!ic.isAble())continue;
				}
				if(UCollision.inBox(x, y, base))return (T)base;
			}else {
				continue;
			}
		}
		return null;
	}
	
	public IStateEvent currentStateEvent() {
		return stateMap.get(Manager.getState());
	}
	
	public IControl currentFocusControl() {
		return focusControl(Manager.getState());
	}
	
	public IControl focusControl(Enum<?> e) {
		IMouseEvent mouseEvent = mouse.get(e);
		return mouseEvent.getFocus();
	}
}
